package org.hackystat.sdsa.analyzer.control.tokenizer;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.sdsa.analyzer.model.Episode;
import org.hackystat.sdsa.analyzer.model.activity.Activity;
import org.hackystat.sdsa.analyzer.model.activity.UnitTestActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.ProductionEditActivity;
import org.hackystat.sdsa.analyzer.model.activity.edit.UnitTestEditActivity;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.RefactorOperator;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.RefactorSubjectType;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.UnaryRefactorActivity;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests unit test pass tokenizer. 
 *  
 * @author Hongbing Kou
 */
public class TestUnitTestPassTokenizer {
  /** Activity list. */
  private List<Activity> activityList;
  
  /**
   * Initializes variable for test. 
   * 
   * @throws Exception If error while creating data.
   */
  @Before public void setUp() throws Exception {
    this.activityList = new ArrayList<Activity>();
    
    XMLGregorianCalendar begin = Tstamp.makeTimestamp("2006-12-11T08:00:00");
    
    String prodFile = "file:/c:/com/foo/Sample.java";
    String testFile = "file:/c:/com/foo/TestSample.java";
    ProductionEditActivity activity1 = new ProductionEditActivity();
    activity1.setTimeStamp(Tstamp.incrementSeconds(begin, 110));
    activity1.setResourceUri(prodFile);
    activity1.setFileSize(127);
    activity1.setNumOfMethods(8);
    activity1.setMethodIncrease(3);
    activity1.setNumOfStatements(35);
    activity1.setStatementIncrease(30);
    this.activityList.add(activity1);

    XMLGregorianCalendar tstamp1 = Tstamp.makeTimestamp("2006-12-20T10:03:27");
    UnitTestEditActivity testEdit1 = new UnitTestEditActivity();
    testEdit1.setTimeStamp(tstamp1);
    testEdit1.setResourceUri(testFile);
    testEdit1.setFileSize(100);
    testEdit1.setNumOfMethods(2);
    testEdit1.setMethodIncrease(2);
    
    testEdit1.setNumOfStatements(100);
    testEdit1.setStatementIncrease(100);
    testEdit1.setNumOfTestAssertions(3);
    testEdit1.setTestAssertionIncrease(3);

    XMLGregorianCalendar tstamp2 = Tstamp.makeTimestamp("2006-12-20T10:06:12");
    UnitTestActivity unitTest1 = new UnitTestActivity();
    unitTest1.setTimeStamp(tstamp2);
    unitTest1.setResourceUri(testFile);
    unitTest1.setFailureMessage("Method getName() can not be recognized");
    this.activityList.add(unitTest1);

    XMLGregorianCalendar tstamp3 = Tstamp.makeTimestamp("2006-12-20T10:10:45");
    RefactorOperator ADD = RefactorOperator.getInstance("ADD");
    RefactorSubjectType METHOD = RefactorSubjectType.getInstance("METHOD");

    UnaryRefactorActivity addActivity = new UnaryRefactorActivity(ADD, METHOD);
    addActivity.setTimeStamp(tstamp3);
    addActivity.setResourceUri(prodFile);
    addActivity.setSubjectName("String getName()");
    this.activityList.add(addActivity);

    XMLGregorianCalendar tstamp4 = Tstamp.makeTimestamp("2006-12-20T10:16:12");
    UnitTestActivity unitTest2 = new UnitTestActivity();
    unitTest2.setTimeStamp(tstamp4);
    unitTest2.setResourceUri(testFile);
    unitTest2.setFailureMessage("");
    unitTest2.setSuccessValue("true");
    this.activityList.add(unitTest2);
    
    XMLGregorianCalendar tstamp5 = Tstamp.makeTimestamp("2006-12-20T10:19:00");
    UnitTestEditActivity testEdit2 = new UnitTestEditActivity();
    testEdit2.setTimeStamp(tstamp5);
    testEdit2.setResourceUri(testFile);
    testEdit2.setFileSize(136);
    testEdit2.setNumOfMethods(3);
    testEdit2.setMethodIncrease(1);
    
    testEdit2.setNumOfStatements(80);
    testEdit2.setStatementIncrease(-1);
    testEdit2.setNumOfTestAssertions(5);
    testEdit2.setTestAssertionIncrease(2);
    this.activityList.add(unitTest2);
  }
  
  /**
   * Tests unit test pass tokenizer on empty dev stream.
   * 
   * @throws Exception If error.
   */
  @Test public void testEmptyDevStream() throws Exception {    
    UnitTestPassTokenizer tokenizer = new UnitTestPassTokenizer();
    List<Activity> emptyActivityList = new ArrayList<Activity>();
    
    List<Episode> episodeList = tokenizer.execute(emptyActivityList);
    assertNotNull("Test return value's nullness", episodeList);
    assertTrue("Test emptiness", episodeList.isEmpty());
  }

  /**
   * Tests unit test pass tokenizer.
   * 
   * @throws Exception If error.
   */
  @Test public void testDevStreamTokenizer() throws Exception {    
    UnitTestPassTokenizer tokenizer = new UnitTestPassTokenizer();
    
    List<Episode> episodeList = tokenizer.execute(this.activityList);
    assertNotNull("Test return value's nullness", episodeList);
    assertEquals("Test episode number", 2, episodeList.size());
    
    Episode episode1 = episodeList.get(0);
    assertEquals("Test size of the first episode", 4, episode1.getActivityNum());
  }
}

